use std::net::{SocketAddr};
use socket2::{Socket, Domain, Type};
use std::mem::MaybeUninit;
use std::net::Ipv4Addr;



fn main() -> std::io::Result<()> {
    
    let socket = Socket::new(Domain::IPV4, Type::DGRAM, None)?;
    socket.set_reuse_port(true)?;

    let address: SocketAddr = "0.0.0.0:8888".parse().unwrap();
    let address = address.into();
    socket.bind(&address)?;

    
    socket.join_multicast_v4(&Ipv4Addr::new(224, 0, 0, 88), &Ipv4Addr::new(0, 0, 0, 0))?;

    /*
    loop {
       let mut buf: [MaybeUninit<u8>; 10] = unsafe{ MaybeUninit::uninit().assume_init()};

       let (amt, src) = socket.recv_from(&mut buf)?;

       println!("recv bytes:{}, src:{:?}", amt, src);
       for elem in &mut buf[..amt] {
           unsafe { elem.assume_init_drop();}
       }
    }
    */
    loop {
       let mut buf: [u8; 10] = [0x00; 10];
        
       let ptr = unsafe {
            std::mem::transmute::<&mut [u8], &mut [MaybeUninit<u8>]>(&mut buf[..])
       };

       let (amt, src) = socket.recv_from(ptr)?;

       println!("recv bytes:{}, src:{:?}", amt, src);
    }

}


//TODO:
//  1. MaybeUninit
//  2. Address (IpAddr, SocketAddr)
//  3. ToSocketAddr
//  4. From<...> && Into Trait
